package cate.game.role.farm.adventure;


import cate.common.table.d.GDFunc;
import cate.common.table.d.GDPlayTime;
import cate.common.table.farm.config.row.FbBuyConsumeRow;
import cate.common.util.GameResult;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import cate.game.role.farm.PlayTimes;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.practice.errorcode.EcResult;

import java.util.Map;

public class QuickFightPlayTimes extends PlayTimes {
    /**
     * 次数是否够用(如果不够用，就会自动购买次数)
     */
    @Override
    public GameResult<Void> available(Role role, int funcId) {
        GameResult<Void> r;
        // 免费次数检测
        r = checkFree(role, funcId);
        if (r.ok()) {
            return r;
        }
        // 余额检测
        r = checkBalance();
        if (r.ok()) {
            return r;
        }
        // 付费检测
        r = checkBuy(role, funcId);
        if (r.ok()) {
            return r;
        }
        return r;
    }

    /**
     * 检测免费挑战是否可用
     */
    @Override
    public GameResult<Void> checkFree(Role role, int funcId) {
        GameResult<Void> r;
        r = checkFree(role, funcId, GDPlayTime.Afford.PRIVILEGE);
        if (r.ok()) {
            return r;
        }
        r = checkFree(role, funcId, GDPlayTime.Afford.ACTIVITY);
        if (r.ok()) {
            return r;
        }
        r = checkFree(role, funcId, GDPlayTime.Afford.BASE);
        if (r.ok()) {
            return r;
        }
        return r.fail("免费次数不足");
    }

    private GameResult<Void> checkFree(Role role, int funcId, byte affordType) {
        GameResult<Void> r = new GameResult<>();
        int available;
        switch (affordType) {
            case GDPlayTime.Afford.BASE:
                available = getBasicFreeTimes(role, funcId);
                break;
            case GDPlayTime.Afford.PRIVILEGE:
                available = getPrivilegeFreeTimes(role, funcId);
                break;
            default:
                available = 0;
        }
        Integer use = freeTimes.get(affordType);
        if (use == null) {
            use = 0;
        }
        if (use < available) {
            this.affordType = affordType;
            return r.success();
        }
        return r.fail();
    }

    private GameResult<Void> checkBalance() {
        GameResult<Void> r = new GameResult<>();
        if (balance >= 1) {
            affordType = GDPlayTime.Afford.BALANCE;
            return r.success();
        }
        return r.fail();
    }

    /**
     * 检测付费购买是否可用(如果有就购买)
     */
    @Override
    public GameResult<Void> checkBuy(Role role, int funcId) {
        GameResult<Void> r;
        r = checkBuy(role, funcId, GDPlayTime.Afford.PRIVILEGE);
        if (r.ok()) {
            return r;
        }
        if (!r.ok()&& r.code==GDPlayTime.CONSUME_ERROR_CODE){
            return r;
        }
        r = checkBuy(role, funcId, GDPlayTime.Afford.ACTIVITY);
        if (r.ok()) {
            return r;
        }
        r = checkBuy(role, funcId, GDPlayTime.Afford.BASE);
        if (r.ok()) {
            return r;
        }
        return r;
    }

    /**
     * 检测各种付费购买是否可用
     */
    private GameResult<Void> checkBuy(Role role, int funcId, byte affordType) {
        GameResult<Void> r = new GameResult<>();
        int available;
        switch (affordType) {
            case GDPlayTime.Afford.BASE:
                available = getBasicBuyTimes(role, funcId);
                break;
            case GDPlayTime.Afford.PRIVILEGE:
                available = getPrivilageBuyTimes(role, funcId);
                break;
            default:
                available = 0;
        }
        Integer use = buyTimes.get(affordType);
        if (use == null) {
            use = 0;
        }
        if (use >= available) {
            if (funcId== GDFunc.QUICK_FIGHT){
                return r.fail("快速补给次数不足");
            }
            return r.fail("挑战次数不足");
        }
        // 如果有次数就尝试购买
        r = checkAfford(role, funcId, use);
        if (r.ok()) {
            buyTimes.put(affordType, use + 1);
            balance++;
            this.affordType = GDPlayTime.Afford.BALANCE;
        }
        return r;
    }

    @JsonIgnore
    @Override
    public int getBuyTime() {
        int buyTime = 0;
        for (Map.Entry<Byte,Integer> entry : buyTimes.entrySet()) {
            if (entry.getKey() != GDPlayTime.Afford.ACTIVITY) {
                buyTime += entry.getValue();
            }
        }
        return buyTime;
    }

    /**
     * 检测能否支付起购买次数
     */
    @Override
    protected GameResult<Void> checkAfford(Role role, int funcId, int use) {
        GameResult<Void> r = new GameResult<>();
        switch (funcId) {
            case GDFunc.QUICK_FIGHT:
                FbBuyConsumeRow consumeRow1 = role.getGame().table.fbBuy.consume.getConsumeRow(funcId, getBuyTime());
                if (consumeRow1 == null) {
                    return r.fail("快速作战消耗配置错误");
                }
                MixRes consume1 = new MixRes(consumeRow1.consumeStr);
                consume1.addList(new MixRes(consumeRow1.extraConsumeStr).multiply(getBuyTime()));
                EcResult<MixResItem> consumeRes1 = consume1.consume(role, null);
                if (!consumeRes1.ok()) {
                    r.fail("钻石数量不足");
                    r.code = GDPlayTime.CONSUME_ERROR_CODE;
                    return r;
                }
                break;
            default:
                // 以后新的副本功能的购买配置默认读 副本购买配置表
                FbBuyConsumeRow consumeRow = role.getGame().table.fbBuy.consume.getConsumeRow(funcId, use);
                if (consumeRow == null) {
                    return r.fail("副本消耗配置错误");
                }
                MixRes consume = new MixRes(consumeRow.consumeStr);
                consume.addList(new MixRes(consumeRow.extraConsumeStr).multiply(getBuyTime()));
                EcResult<MixResItem> consumeRes = consume.consume(role, null);
                if (!consumeRes.ok()) {
                    return r.fail(consumeRes.message);
                }
                break;
        }
        return r.success();
    }
}
